﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nox.Amuse.Model;
using System.Windows.Documents;
using System.Windows;
using System.Windows.Media;

namespace Nox.Amuse.Helpers
{
    static class LineProcessor
    {
        /// <summary>
        /// The just received LineItem
        /// </summary>
        static LineItem currentLineItem;
        /// <summary>
        /// The currently in use Formatting Properties
        /// </summary>
        static FormattingProperties currentFormattingProps;
        /// <summary>
        /// The currently in use Foreground colour
        /// </summary>
        static FormattingColor currentForeground;
        /// <summary>
        /// The currently in use Background colour
        /// </summary>
        static FormattingColor currentBackground;
        /// <summary>
        /// The current formatting reset status
        /// </summary>
        static bool currentisReset;
        /// <summary>
        /// The list of currently being processed LineItemRun objects
        /// </summary>
        static List<LineItemRun> currentLineItemRunList;
        /// <summary>
        /// The currently being constructioned array of Inlines
        /// </summary>
        static Inline[] currentInlines;
        /// <summary>
        /// The current LineItemRun being processed
        /// </summary>
        static LineItemRun currentLineItemRun;
        /// <summary>
        /// The current Run being created
        /// </summary>
        static Run currentRun;

        public static Inline[] FormatLine(LineItem lineitem)
        {
            currentLineItem = lineitem;

            //Reset starting values
            currentFormattingProps = FormattingProperties.None;
            currentForeground = FormattingColor.Unset;
            currentBackground = FormattingColor.Unset;
            currentisReset = false;

            //Set previous values
            if (currentLineItem.PreviousLine != null)
            {
                currentFormattingProps = currentLineItem.PreviousLine.EndState.Formatting;
                currentForeground = currentLineItem.PreviousLine.EndState.Foreground;
                currentBackground = currentLineItem.PreviousLine.EndState.Background;
                currentisReset = currentLineItem.PreviousLine.EndState.HasResetCode;
            }

            currentLineItemRunList = currentLineItem.GetFormattedLineRuns();
            currentInlines = new Inline[currentLineItemRunList.Count];

            for (int i = 0; i < currentInlines.Length; i++)
            {
                currentLineItemRun = currentLineItemRunList[i];

                if (currentLineItemRun.Formatting == (currentLineItemRun.Formatting | FormattingProperties.Bold))
                    currentFormattingProps = currentFormattingProps | FormattingProperties.Bold;
                if (currentLineItemRun.Formatting == (currentLineItemRun.Formatting | FormattingProperties.Flash))
                    currentFormattingProps = currentFormattingProps | FormattingProperties.Flash;
                if (currentLineItemRun.Formatting == (currentLineItemRun.Formatting | FormattingProperties.Underline))
                    currentFormattingProps = currentFormattingProps | FormattingProperties.Underline;
                if (currentLineItemRun.Formatting == (currentLineItemRun.Formatting | FormattingProperties.Invert))
                    currentFormattingProps = currentFormattingProps | FormattingProperties.Invert;
                if (currentLineItemRun.Foreground != FormattingColor.Unset)
                    currentForeground = currentLineItemRun.Foreground;
                if (currentLineItemRun.Background != FormattingColor.Unset)
                    currentBackground = currentLineItemRun.Background;
                currentisReset = currentLineItemRun.HasResetCode;

                if (currentisReset)
                {
                    currentFormattingProps = FormattingProperties.None;
                    currentForeground = FormattingColor.Unset;
                    currentBackground = FormattingColor.Unset;
                    currentisReset = false;
                }

                currentRun = new Run(currentLineItemRun.RunText);

                if (currentFormattingProps == (currentFormattingProps | FormattingProperties.Invert))
                {
                    var temp = currentForeground;
                    currentForeground = currentBackground;
                    currentBackground = temp;
                }

                if (currentFormattingProps == (currentFormattingProps | FormattingProperties.Bold))
                {
                    currentRun.FontWeight = FontWeights.Bold;
                    currentRun.Foreground = GetRunColor(currentForeground, true, Brushes.WhiteSmoke); // HACK: Fix me
                }
                else
                {
                    currentRun.Foreground = GetRunColor(currentForeground, false, Brushes.WhiteSmoke); // HACK: Fix me
                }
                currentRun.Background = GetRunColor(currentBackground, false, Brushes.Transparent);

                if (currentFormattingProps == (currentFormattingProps | FormattingProperties.Flash))
                    currentRun.FontStyle = FontStyles.Italic;
                if (currentFormattingProps == (currentFormattingProps | FormattingProperties.Underline))
                    currentRun.TextDecorations = TextDecorations.Underline;

                currentInlines[i] = currentRun;
            }

            return currentInlines;
        }

        /// <summary>
        /// Returns a pre-set brush of the correct Color for the given FormattingColor value and Bold value
        /// </summary>
        /// <param name="color">The color value</param>
        /// <param name="isBold">If the color is a bright color or not</param>
        /// <param name="defaultBrush">The brush to use if the color is not set</param>
        /// <returns>A brush of the correct color</returns>
        private static Brush GetRunColor(FormattingColor color, bool isBold, Brush defaultBrush)
        {
            if (isBold)
            {
                switch (color)
                {
                    case FormattingColor.Black:
                        return Brushes.DarkGray;
                    case FormattingColor.Red:
                        return Brushes.Red;
                    case FormattingColor.Green:
                        return Brushes.LimeGreen;
                    case FormattingColor.Yellow:
                        return Brushes.Yellow;
                    case FormattingColor.Blue:
                        return Brushes.Blue;
                    case FormattingColor.Magenta:
                        return Brushes.Magenta;
                    case FormattingColor.Cyan:
                        return Brushes.Cyan;
                    case FormattingColor.White:
                        return Brushes.White;
                    default:
                        return defaultBrush;
                }
            }
            else
            {
                switch (color)
                {
                    case FormattingColor.Black:
                        return Brushes.Black;
                    case FormattingColor.Red:
                        return Brushes.Maroon;
                    case FormattingColor.Green:
                        return Brushes.ForestGreen;
                    case FormattingColor.Yellow:
                        return Brushes.Olive;
                    case FormattingColor.Blue:
                        return Brushes.Navy;
                    case FormattingColor.Magenta:
                        return Brushes.Purple;
                    case FormattingColor.Cyan:
                        return Brushes.Teal;
                    case FormattingColor.White:
                        return Brushes.Silver;
                    default:
                        return defaultBrush;
                }
            }
        }

    }
}
